package com.hougong.lineclient.transport;



import com.hougong.lineclient.common.Constants;
import com.hougong.lineclient.common.GlobalData;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ClientConfig {
    private static final Logger LOGGER=LoggerFactory.getLogger(ClientConfig.class);
    public volatile static Channel channel=null;
    private static ClientConfig clientConfig=new ClientConfig(Constants.host,Constants.tcpPort);
    public static Bootstrap b=null;
    private static String host;
    private static int port;
    public static ClientConfig getInstance(){
        return clientConfig;
    }

    public static void closeChannel() throws InterruptedException {
        if(channel!=null){
            AcceptHandler.needReConn.set(false);
            ChannelFuture close = channel.close().sync();
            channel=null;
        }
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    private ClientConfig() {

    }


    private ClientConfig(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public static final Bootstrap getConfigBootstrap() {
        if(b==null){
            synchronized (ClientConfig.class){
                if(b==null){
                    EventLoopGroup group = new NioEventLoopGroup();
                    b = new Bootstrap();
                    b.group(group) // 注册线程池
                            .channel(NioSocketChannel.class) // 使用NioSocketChannel来作为连接用的channel类
                            .option(ChannelOption.SO_KEEPALIVE, true)
                            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS,10000)
                            .handler(new ChannelInitializer<SocketChannel>() { // 绑定连接初始化器
                                @Override
                                protected void initChannel(SocketChannel ch) throws Exception {
                                    ch.pipeline().addLast(new ProtocolDecoder());
                                    ch.pipeline().addLast(new AcceptHandler());
                                    ch.pipeline().addLast(new ProtocolEncoder());
                                }
                            });
                    b.remoteAddress(new InetSocketAddress(host, port));
                }
            }
        }
        return b;
    }

    public void connectListen(final Bootstrap bootstrap, final int times) throws InterruptedException {
        final Lock lock = new ReentrantLock();
        final Condition condition=lock.newCondition();
        if (times > 0) {
            System.out.println("尝试连接一次");
            ChannelFuture sync = bootstrap.connect().awaitUninterruptibly();
           // System.out.println("堵塞任务完成"+sync.isDone());
            if(sync.isSuccess()){
                System.out.println("成功连接到服务器....");
                channel = sync.channel();
            }else {
                Thread.sleep(10000);
               // LOGGER.info("10秒后重新连接"+getHost()+":"+getPort());
                System.out.println("10秒后重新连接"+getHost()+":"+getPort());
                connectListen(bootstrap, times - 1);
            }
        }else {
            if(GlobalData.token!=null){
                LOGGER.error("可能是服务器关闭了！");
                System.exit(0);
            }
        }
    }


    /**
     * 连接到服务器循环连接
     *
     * @throws UnsupportedEncodingException
     * @throws InterruptedException
     */
    public void connectToServer() throws  InterruptedException {
        System.out.println("尝试连接3次");
        final Bootstrap configBootstrap = getConfigBootstrap();
        connectListen(configBootstrap, 3);
    }
}
